﻿/* Autor: Achim Schnell */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using AppFx.ComponentModel.Descriptive;

namespace AppFx.Collections
{
	/// <summary>
	/// Eine Liste, welche ITypedList implementiert und damit
	/// die Anpassung der zur Verfügung gestellten PropertyDescriptors
	/// vereinfacht.
	/// </summary>
	/// <typeparam name="T">Typ der Objekte, die in der Liste verarbeitet werden soll.</typeparam>
	public class TypedBindingList<T> : BindingList<T>, ITypedList
	{
		#region Properties

		/// <summary>
		/// Gibt den TypeDescriptionProvider zurück, der zur Erstellung
		/// von PropertyDescripors verwendet wird. Die dort erzeugten
		/// PropertyDescriptors dienen als Rückgabewert bei der Implementierung
		/// von ITypedList.
		/// </summary>
		public ITypeDescriptionProvider DescriptionProvider { get; set; }

		/// <summary>
		/// Gibt die gespeicherten PropertyDescriptors zurück.
		/// Die Zuweisung von NULL resultiert in einer Neuerstellung
		/// der PropertyDescriptors beim erneuten Aufruf von ITypedList.GetItemProperties.
		/// </summary>
		protected IList<PropertyDescriptor> Descriptors { get; set; }

		/// <summary>
		/// Gibt oder setzt den Namen der Liste.
		/// Diese Eigenschaft ist (eigentlich) veraltet.
		/// </summary>
		public string ListName { get; set; }

		#endregion

		#region Constructors

		/// <summary>
		/// Erzeugt eine neue TypedBindingList.
		/// </summary>
		public TypedBindingList()
		{
			DescriptionProvider = new DeepCompiledTypeDescriptionProvider();
		}

		#endregion

		#region Methods

		/// <summary>
		/// Gibt die <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> zurück, die die Eigenschaften für jedes Element darstellt, das bei der Datenbindung verwendet wird.
		/// </summary>
		/// <param name="listAccessors">Ein Array von <see cref="T:System.ComponentModel.PropertyDescriptor"/>-Objekten, die in der Auflistung als bindbar gesucht werden sollen.Dieser Wert kann null sein.</param>
		/// <returns>
		/// Die <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/>, die die Eigenschaften für jedes Element darstellt, das bei der Datenbindung verwendet wird.
		/// </returns>
		public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
		{
			if (DescriptionProvider == null)
				throw new NullReferenceException("The DescriptionProvider for TypedBindingList must not be NULL.");
			if (Descriptors == null)
				Descriptors = DescriptionProvider.GetDescriptors(typeof(T));
			return new PropertyDescriptorCollection(Descriptors.ToArray());

		}

		/// <summary>
		/// Gibt den Namen der Liste zurück.
		/// </summary>
		/// <param name="listAccessors">Ein Array von <see cref="T:System.ComponentModel.PropertyDescriptor"/>-Objekten, für die der Listenname zurückgegeben wird.Dieser Wert kann null sein.</param>
		/// <returns>
		/// Der Name der Liste.
		/// </returns>
		public string GetListName(PropertyDescriptor[] listAccessors)
		{
			return ListName;
		}

		#endregion
	}
}
